#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <iostream>
#include <signal.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
using namespace std;

static const char *ip = "192.168.232.128";
static const int port = 12345;

void event_cb(bufferevent *bufev, short event_type, void *args) {
    cout << "[E]" << flush;
    if (event_type & BEV_EVENT_TIMEOUT && event_type & BEV_EVENT_READING) {
        cout << "timeout" << endl;
        // bufferevent_enable(bufev, EV_READ);  // 可以使 bufferevent 重新可读
        bufferevent_free(bufev);
    } else if (event_type & BEV_EVENT_ERROR) {
        cout << "error" << endl;
        bufferevent_free(bufev);
    } else {
        cout << "others" << endl;
    }
}
void read_cb(bufferevent *bufev, void *args) {
    cout << "[R]" << flush;
    char data[1024] = {0};
    int len = bufferevent_read(bufev, data, sizeof(data) - 1);
    if (len <= 0) return;
    if (strstr(data, "quit") != nullptr) {
        cout << "quit" << endl;
        bufferevent_free(bufev);    // 释放时因为之前的参数会自动关闭socket
    }
    cout << data << flush;
    bufferevent_write(bufev, "okk\n", 4);
}
void write_cb(bufferevent *bufev, void *args) {
    cout << "[W]" << flush;
}

void listener_cb(evconnlistener *ev, evutil_socket_t sock, sockaddr* addr, int addrlen, void *args) {
    cout << "listener_cb" << endl;
    event_base *base = (event_base*)args;
    // 创建 bufferevent 上下文，清理时关闭对应 socket
    bufferevent *bufev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
    // 添加监控事件
    bufferevent_enable(bufev, EV_READ | EV_WRITE);
    // 设置水位
    bufferevent_setwatermark(bufev, EV_READ, 5, 10);
    // 先是低水位，后是高水位，设置成0时无限制
    // 设置写的水位时类似，但是在 telnet 上看不出效果
    // 写的高水位无效

    // 设置超时时间
    timeval t1 {3, 0};
    bufferevent_set_timeouts(bufev, &t1, 0);    // 这里只设置了读超时，最后一个参数时写超时

    // 设置回调函数
    bufferevent_setcb(bufev, read_cb, write_cb, event_cb, base);

}

int main() {
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
        cerr << "set pipe signal error" << endl;
        return 1;
    }

    event_base *base = event_base_new();
    if (base) {
        cout << "create new event base" << endl;
    }

    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    inet_pton(AF_INET, ip, &sin.sin_addr);

    evconnlistener *ev = evconnlistener_new_bind(base, listener_cb, base, 
        LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, 5,
        (sockaddr*)&sin, sizeof(sin));


    // 进入事件主循环
    event_base_dispatch(base);
    cout << "111" << endl;
    event_base_free(base);

}